using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using FitnessMVC.Data;
using System.Security;
using FitnessMVCWeb.Helpers;

namespace FitnessMVCWeb.Controllers
{
    // ViewModel for private profiles
    public class LimitedProfileInfo
    {
        public string UserName { get; set; }
        public int PictureID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public class UserProfileController : Controller
    {
        IFitnessRepository fitnessRepository;

        // Pattern from NerdDinner
        // (Poor Mans) Dependency Injection enabled constructors

        public UserProfileController()
            : this(new SqlFitnessRepository()) {
        }

        public UserProfileController(IFitnessRepository repository)
        {
            fitnessRepository = repository;
        }

        //
        // GET: /UserProfile/

        [Authorize]        
        public ActionResult Index()
        {
            if (User == null)
                return View("LogOn");

            UserProfile up = fitnessRepository.GetUserProfile(User.Identity.Name);
            if (up == null)
                return View("Create");

            return View(up);
        }       

        // GET: /UserProfile/Details/jacob4u2
        [Authorize]
        public ActionResult Details(string userName, bool? asJson)
        {
            if (User == null)
                return View("LogOn");

            UserProfile up = fitnessRepository.GetUserProfile(userName);

            if (up == null)
                return View("ProfileNotFound");

            // If the profile is public or the requesting user is a buddy or the 
            // user is requesting their own profile, return the full profile.
            if ( up.IsPublic || (userName == User.Identity.Name ||
                    fitnessRepository.AreUsersBuddies(userName, User.Identity.Name) ))
            {
                if (!asJson.HasValue || !asJson.Value)
                    return View(up);

                return Json(up);
            }

            // Otherwise, return a limited profile.
            return View(GetLimitedProfileInfoFromProfile(up));
        }       

        //
        // /UserProfile/Buddies
        // /UserProfile/Buddies/jacob4u2
        [Authorize]
        public ActionResult Buddies(string userName, bool? asJson)
        {
            if ( User == null )
                return View("LogOn");

            List<LimitedProfileInfo> buddies = new List<LimitedProfileInfo>();

            if (string.IsNullOrEmpty(userName))
                userName = User.Identity.Name;
            
            var userBuddies = from ub in fitnessRepository.GetUserBuddies(userName)
                              select ub;

            buddies = (from buddy in userBuddies
                       join profile in fitnessRepository.GetAllProfiles() on buddy.UserId equals profile.UserID
                       select GetLimitedProfileInfoFromProfile(buddy, profile)
                       ).ToList();

            if (!asJson.HasValue || !asJson.Value)
                return View(buddies);

            return Json(buddies);
        }
        
        private LimitedProfileInfo GetLimitedProfileInfoFromProfile(User u, UserProfile profile)
        {
            return new LimitedProfileInfo()
                       {
                           UserName = u.UserName,
                           FirstName = profile.FirstName,
                           LastName = profile.LastName,
                           PictureID = profile.ProfilePicID ?? 1
                       };
        }

        private LimitedProfileInfo GetLimitedProfileInfoFromProfile(UserProfile up)
        {
            return GetLimitedProfileInfoFromProfile(fitnessRepository.GetUserByUserId(up.UserID), up);
        }
       
        //
        // POST: /UserProfile/Create

        // TODO: Do some antiforgerytoken checking...
        [AcceptVerbs(HttpVerbs.Post), Authorize]
        public ActionResult Create([Bind(Exclude="ProfileID,ProfilePicID")]UserProfile up)
        {
            if (User == null)
                return View("LogOn");

            try
            {
                up.ProfilePicID = null;
                var usr = fitnessRepository.GetUserByName(User.Identity.Name);
                up.UserID = usr.UserId;

                if (up.IsValid)
                {
                    fitnessRepository.AddUserProfile(up);
                    fitnessRepository.Save();

                    return Index();
                }
                else
                {
                    ModelState.AddModelErrors(up.GetRuleViolations());
                    
                    return View(up);
                }

            }
            catch
            {
                return View("Error");
            }
        }

        //
        // GET: /UserProfile/Edit/5
 
        [Authorize]
        public ActionResult Edit(int id)
        {
            if (User == null)
                return View("LogOn");

            var up = fitnessRepository.GetUserProfile(User.Identity.Name);

            return View(up);
        }

        //
        // POST: /UserProfile/Edit/5

        [AcceptVerbs(HttpVerbs.Post)]
        [Authorize]
        public ActionResult Edit([Bind(Exclude="PictureID")]UserProfile up)
        {
            // TODO: Verify the user doing submitting the values is the same user.
            if ( User == null )
                return View("LogOn");
            
            try
            {
                fitnessRepository.UpdateUserProfile(up);
                fitnessRepository.Save();

                return RedirectToAction("Index");
            }
            catch
            {
                ModelState.AddModelErrors(up.GetRuleViolations());
                return View(up);
            }
        }

        private UserProfile FillUserProfile(FormCollection collection)
        {
            return new UserProfile()
            {
                FirstName = collection["FirstName"],
                LastName = collection["LastName"],
                AboutMe = collection["AboutMe"],
                Hometown = collection["Hometown"],
                BirthDate = DateTime.Parse(collection["BirthDate"]),
                UserID = new Guid(collection["UserID"]),
                ProfileID = Int32.Parse(collection["ProfileID"]),
                MemberSince = DateTime.Parse(collection["MemberSince"]),
                IsPublic = Boolean.Parse(collection["IsPublic"]),
                Sex = Char.Parse(collection["Sex"])
            };
            
        }
    }
}
